package org.convallaria.system.biz.service.sys;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import org.convallaria.system.biz.entity.SysMenu;

import java.util.List;
import java.util.Set;

/**
 * 系统菜单服务接口
 * 
 * 功能特性：
 * - 菜单基础CRUD操作
 * - 菜单树结构管理
 * - 菜单权限管理
 * - 菜单角色关联管理
 * - 菜单缓存管理
 * 
 * @author convallaria
 * @since 1.0.0
 */
public interface SysMenuService extends IService<SysMenu> {

    /**
     * 分页查询菜单列表
     * 
     * @param pageNum 页码
     * @param pageSize 页大小
     * @param menuName 菜单名称（可选）
     * @param menuType 菜单类型（可选）
     * @param status 状态（可选）
     * @param tenantId 租户ID（可选）
     * @return 菜单分页列表
     */
    IPage<SysMenu> pageMenus(Integer pageNum, Integer pageSize, String menuName, String menuType, String status, Long tenantId);

    /**
     * 根据菜单ID获取菜单信息（带缓存）
     * 
     * @param menuId 菜单ID
     * @return 菜单信息
     */
    SysMenu getMenuById(Long menuId);

    /**
     * 获取菜单树结构
     * 
     * @param tenantId 租户ID
     * @return 菜单树列表
     */
    List<SysMenu> getMenuTree(Long tenantId);

    /**
     * 根据父菜单ID获取子菜单列表
     * 
     * @param parentId 父菜单ID
     * @param tenantId 租户ID
     * @return 子菜单列表
     */
    List<SysMenu> getChildrenMenus(Long parentId, Long tenantId);

    /**
     * 获取用户菜单树
     * 
     * @param userId 用户ID
     * @param tenantId 租户ID
     * @return 用户菜单树
     */
    List<SysMenu> getUserMenuTree(Long userId, Long tenantId);

    /**
     * 获取角色的菜单权限
     * 
     * @param roleId 角色ID
     * @param tenantId 租户ID
     * @return 菜单权限列表
     */
    List<SysMenu> getRoleMenus(Long roleId, Long tenantId);

    /**
     * 更新菜单信息（清除相关缓存）
     * 
     * @param menu 菜单信息
     * @return 是否成功
     */
    boolean updateMenu(SysMenu menu);

    /**
     * 删除菜单（清除相关缓存）
     * 
     * @param menuId 菜单ID
     * @return 是否成功
     */
    boolean deleteMenu(Long menuId);

    /**
     * 批量删除菜单（清除相关缓存）
     * 
     * @param menuIds 菜单ID列表
     * @return 是否成功
     */
    boolean deleteMenus(List<Long> menuIds);

    /**
     * 刷新菜单缓存
     * 
     * @param menu 菜单信息
     * @return 菜单信息
     */
    SysMenu refreshMenuCache(SysMenu menu);

    /**
     * 获取菜单的所有权限标识
     * 
     * @param menuId 菜单ID
     * @return 权限标识集合
     */
    Set<String> getMenuPermissions(Long menuId);

    /**
     * 获取用户的所有菜单权限
     * 
     * @param userId 用户ID
     * @param tenantId 租户ID
     * @return 权限标识集合
     */
    Set<String> getUserMenuPermissions(Long userId, Long tenantId);

    /**
     * 获取用户的所有权限（简化版本，不需要租户ID）
     * 
     * @param userId 用户ID
     * @return 权限标识集合
     */
    Set<String> getUserPermissions(Long userId);

    /**
     * 检查菜单名称是否唯一
     * 
     * @param menuName 菜单名称
     * @param menuId 菜单ID（更新时排除自己）
     * @param parentId 父菜单ID
     * @param tenantId 租户ID
     * @return 是否唯一
     */
    boolean isMenuNameUnique(String menuName, Long menuId, Long parentId, Long tenantId);

    /**
     * 检查菜单路径是否唯一
     * 
     * @param path 菜单路径
     * @param menuId 菜单ID（更新时排除自己）
     * @param tenantId 租户ID
     * @return 是否唯一
     */
    boolean isMenuPathUnique(String path, Long menuId, Long tenantId);

    /**
     * 检查菜单是否被角色使用
     * 
     * @param menuId 菜单ID
     * @return 是否被使用
     */
    boolean isMenuInUse(Long menuId);

    /**
     * 检查菜单是否有子菜单
     * 
     * @param menuId 菜单ID
     * @return 是否有子菜单
     */
    boolean hasChildrenMenus(Long menuId);

    /**
     * 构建菜单树结构
     * 
     * @param menus 菜单列表
     * @return 菜单树列表
     */
    List<SysMenu> buildMenuTree(List<SysMenu> menus);

    /**
     * 获取菜单的完整路径
     * 
     * @param menuId 菜单ID
     * @return 菜单路径
     */
    String getMenuPath(Long menuId);

    /**
     * 获取菜单的层级深度
     * 
     * @param menuId 菜单ID
     * @return 层级深度
     */
    int getMenuDepth(Long menuId);

    /**
     * 根据权限标识获取菜单
     * 
     * @param perms 权限标识
     * @param tenantId 租户ID
     * @return 菜单信息
     */
    SysMenu getMenuByPerms(String perms, Long tenantId);

    /**
     * 获取所有按钮权限
     * 
     * @param tenantId 租户ID
     * @return 按钮权限列表
     */
    List<SysMenu> getButtonPermissions(Long tenantId);
}
